﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Windows.Controls;
using Safe_Driving.EasyCalendar.Model;


namespace Safe_Driving.EasyCalendar.Controler
{
    /// <summary>
    ///
    ///     <MyNamespace:EasyCalendar/>
    ///
    /// </summary>
    public partial class EasyCalendar : ItemsControl
    {
        static EasyCalendar()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(EasyCalendar), new FrameworkPropertyMetadata(typeof(EasyCalendar)));
            
            //CommandManager.RegisterClassCommandBinding(typeof(EasyCalendar), new CommandBinding(Week_selected, new ExecutedRoutedEventHandler(OnExecutedWeek_selected), new CanExecuteRoutedEventHandler(OnCanExecuteWeek_selected)));
            CommandManager.RegisterClassCommandBinding(typeof(EasyCalendar), new CommandBinding(NextDay, new ExecutedRoutedEventHandler(OnExecutedNextDay), new CanExecuteRoutedEventHandler(OnCanExecuteNextDay)));
            CommandManager.RegisterClassCommandBinding(typeof(EasyCalendar), new CommandBinding(PreviousDay, new ExecutedRoutedEventHandler(OnExecutedPreviousDay), new CanExecuteRoutedEventHandler(OnCanExecutePreviousDay)));
        }

        #region previous/next

            #region Command

                public static readonly RoutedCommand NextDay = new RoutedCommand("NextDay", typeof(EasyCalendar));
                public static readonly RoutedCommand PreviousDay = new RoutedCommand("PreviousDay", typeof(EasyCalendar));
        
                private static void OnCanExecuteNextDay(object sender, CanExecuteRoutedEventArgs e)
                {
                    ((EasyCalendar)sender).OnCanExecuteNextDay(e);
                }

                private static void OnExecutedNextDay(object sender, ExecutedRoutedEventArgs e)
                {
                    ((EasyCalendar)sender).OnExecutedNextDay(e);
                }

                protected virtual void OnCanExecuteNextDay(CanExecuteRoutedEventArgs e)
                {
                    e.CanExecute = true;
                    e.Handled = false;
                }

                private static void OnCanExecutePreviousDay(object sender, CanExecuteRoutedEventArgs e)
                {
                    ((EasyCalendar)sender).OnCanExecutePreviousDay(e);
                }

                private static void OnExecutedPreviousDay(object sender, ExecutedRoutedEventArgs e)
                {
                    ((EasyCalendar)sender).OnExecutedPreviousDay(e);
                }

                protected virtual void OnCanExecutePreviousDay(CanExecuteRoutedEventArgs e)
                {
                    e.CanExecute = true;
                    e.Handled = false;
                }

            #endregion

            protected virtual void OnExecutedNextDay(ExecutedRoutedEventArgs e)
            {
                jump_week(-1);
            
                e.Handled = true;
            }

            

            protected virtual void OnExecutedPreviousDay(ExecutedRoutedEventArgs e)
            {
                jump_week(1);

                e.Handled = true;
            }


            public void jump_week(int nb)
            {
                MondayDate -= TimeSpan.FromDays(7 * nb);
                this.ItemsSource = Events.ByDate(MondayDate);
                
                CalendarDay monday = this.GetTemplateChild("Monday") as CalendarDay;
                CalendarDay tuesday = this.GetTemplateChild("Tuesday") as CalendarDay;
                CalendarDay wednesday = this.GetTemplateChild("Wednesday") as CalendarDay;
                CalendarDay thursday = this.GetTemplateChild("Thursday") as CalendarDay;
                CalendarDay friday = this.GetTemplateChild("Friday") as CalendarDay;
                CalendarDay saturday = this.GetTemplateChild("Saturday") as CalendarDay;
                CalendarDay sunday = this.GetTemplateChild("Sunday") as CalendarDay;

                monday.initDates();
                tuesday.initDates();
                wednesday.initDates();
                thursday.initDates();
                friday.initDates();
                saturday.initDates();
                sunday.initDates();

                monday.jump_2_x_week(nb);
                tuesday.jump_2_x_week(nb);
                wednesday.jump_2_x_week(nb);
                thursday.jump_2_x_week(nb);
                friday.jump_2_x_week(nb);
                saturday.jump_2_x_week(nb);
                sunday.jump_2_x_week(nb);

            }


            private DateTime getMondayDate(DateTime d)
            {
                while((int)d.DayOfWeek != 1) {
                    d -= TimeSpan.FromDays(1);
                }

                return d;
            }
            

            public void initDate()
            {
                //On recale MondayDate sur la bonne valeur
                MondayDate = getMondayDate(MondayDate);

                Expander date_expander = this.GetTemplateChild("date_expander") as Expander;
                date_expander.Header = MondayDate.Year;

                CalendarDay monday = this.GetTemplateChild("Monday") as CalendarDay;
                CalendarDay tuesday = this.GetTemplateChild("Tuesday") as CalendarDay;
                CalendarDay wednesday = this.GetTemplateChild("Wednesday") as CalendarDay;
                CalendarDay thursday = this.GetTemplateChild("Thursday") as CalendarDay;
                CalendarDay friday = this.GetTemplateChild("Friday") as CalendarDay;
                CalendarDay saturday = this.GetTemplateChild("Saturday") as CalendarDay;
                CalendarDay sunday = this.GetTemplateChild("Sunday") as CalendarDay;

                monday.initDates();
                tuesday.initDates();
                wednesday.initDates();
                thursday.initDates();
                friday.initDates();
                saturday.initDates();
                sunday.initDates();

                this.ItemsSource = Events.ByDate(MondayDate);
            }


           

        #endregion

        
 



        #region MondayDate

            #region Property

            public static readonly DependencyProperty MondayDateProperty =
                        DependencyProperty.Register("MondayDate", typeof(DateTime), typeof(EasyCalendar),
                            new FrameworkPropertyMetadata((DateTime)DateTime.Now, onCurrentDateChanged));


                public DateTime MondayDate
                {
                    get { return (DateTime)GetValue(MondayDateProperty); }
                    set { SetValue(MondayDateProperty, value); }
                }

                protected static void onCurrentDateChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
                {
                    ((EasyCalendar)obj).onCurrentDateChanged(args);
                }

                protected virtual void onCurrentDateChanged(DependencyPropertyChangedEventArgs e)
                {}

            #endregion

        #endregion


        #region Events

            public static readonly DependencyProperty EventsProperty =
                DependencyProperty.Register("Events", typeof(IEnumerable<EventCal>), typeof(EasyCalendar),
                new FrameworkPropertyMetadata(null, new PropertyChangedCallback(EasyCalendar.OnEventsChanged)));

            public IEnumerable<EventCal> Events
            {
                get { return (IEnumerable<EventCal>)GetValue(EventsProperty); }
                set { SetValue(EventsProperty, value); }
            }

            private static void OnEventsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                ((EasyCalendar)d).OnEventsChanged(e);
            }

            protected virtual void OnEventsChanged(DependencyPropertyChangedEventArgs e)
            {
                FilterAppointments();
            }

            private void FilterAppointments()
            {
                DateTime byDate = MondayDate;
                this.ItemsSource = Events.ByDate(byDate);
            }

        #endregion



        #region ItemsControl Container Override

            protected override DependencyObject GetContainerForItemOverride()
            {
                return new EventCalendar();
            }

            protected override bool IsItemItsOwnContainerOverride(object item)
            {
                return (item is EventCalendar);
            }

        #endregion
    
    }



    [TemplatePart(Type = typeof(Microsoft.Windows.Controls.Calendar), Name = EasyCalendar.CALENDAR_NAME)]
    public partial class EasyCalendar : ItemsControl
    {
        private const string CALENDAR_NAME = "week_select_calendar";

        private Microsoft.Windows.Controls.Calendar m_Calendar;

        #region Overrides Methods

            public override void OnApplyTemplate()
            {
                base.OnApplyTemplate();

                this.m_Calendar = this.Template.FindName(CALENDAR_NAME, this) as Microsoft.Windows.Controls.Calendar;

                if (this.m_Calendar != null)
                {
                    this.m_Calendar.SelectedDatesChanged += this.week_select_calendar_SelectedDatesChanged;
                    this.m_Calendar.Loaded += this.cal_Loaded;
                }
            }

        #endregion

        private void week_select_calendar_SelectedDatesChanged(object sender, SelectionChangedEventArgs e)
        {
            CalendarDay day = this.GetTemplateChild(
                ((DateTime)((Microsoft.Windows.Controls.Calendar)sender).SelectedDate).DayOfWeek.ToString()
                ) as CalendarDay;
            ((Microsoft.Windows.Controls.Calendar)sender).DisplayDate = (DateTime)(((Microsoft.Windows.Controls.Calendar)sender).SelectedDate);

            jump_2_x_week(how_many_weeks(day.CurrentDate, (DateTime)((Microsoft.Windows.Controls.Calendar)sender).SelectedDate));
            
            
            Expander date_expander = this.GetTemplateChild("date_expander") as Expander;
            date_expander.IsExpanded = false;
        }

        private void cal_Loaded(object sender, RoutedEventArgs e)
        {
            this.initDate();
        }

        private int how_many_weeks(DateTime currentDate, DateTime calendar_date)
        {
            TimeSpan interval = currentDate - calendar_date;
            double inter = interval.TotalDays / (double)7;
            int inter_int = Convert.ToInt32(Math.Truncate(inter));
            if (inter_int > 0)
            {
                return inter_int;
            }
            else
            {
                return inter_int;
            }
        }


        public void jump_2_x_week(int nb_week)
        {
            MondayDate -= TimeSpan.FromDays(7 * nb_week);
            this.ItemsSource = Events.ByDate(MondayDate);

            CalendarDay monday = this.GetTemplateChild("Monday") as CalendarDay;
            CalendarDay tuesday = this.GetTemplateChild("Tuesday") as CalendarDay;
            CalendarDay wednesday = this.GetTemplateChild("Wednesday") as CalendarDay;
            CalendarDay thursday = this.GetTemplateChild("Thursday") as CalendarDay;
            CalendarDay friday = this.GetTemplateChild("Friday") as CalendarDay;
            CalendarDay saturday = this.GetTemplateChild("Saturday") as CalendarDay;
            CalendarDay sunday = this.GetTemplateChild("Sunday") as CalendarDay;

            monday.jump_2_x_week(nb_week);
            tuesday.jump_2_x_week(nb_week);
            wednesday.jump_2_x_week(nb_week);
            thursday.jump_2_x_week(nb_week);
            friday.jump_2_x_week(nb_week);
            saturday.jump_2_x_week(nb_week);
            sunday.jump_2_x_week(nb_week);
        }

    }
}
